local SHADER = "shaders/vfx_particle.ksh"
local TEXTURE = resolvefilepath("images/fx/fx_rainbow/fx_rainbow.tex")

local assets =
{
    Asset("SHADER", SHADER),
    Asset("IMAGE", TEXTURE),
}

--------------------------------------------------------------------------

local SCALE_ENVELOPE_NAME_RAINBOW_POINT_NPC_FX = "SCALE_ENVELOPE_NAME_RAINBOW_POINT_NPC_FX"
local COLOUR_ENVELOPE_NAME_RAINBOW_NPC_FX = "COLOUR_ENVELOPE_NAME_RAINBOW_NPC_FX"
-- local NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINTS_DATA = {
--     [1] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_RED" , Vector3(255,0,0) },
--     [2] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_ORANGE" , Vector3(255,165,0) },
--     [3] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_YELLOW" , Vector3(255,255,0) },
--     [4] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_GREEN" , Vector3(0,255,0) },
--     [5] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_CYAN" , Vector3(0,255,255) },
--     [6] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_BLUE" , Vector3(0,0,255) },
--     [7] = {"NPC_FX_COLOUR_ENVELOPE_NAME_RAINBOW_POINT_PURPLE" , Vector3(139,0,255) }
-- }
--------------------------------------------------------------------------

local function IntColour(r, g, b, a)
    return { r / 255, g / 255, b / 255, a / 255 }
end

local function RandomVectorDelta(num)
    if num == nil or num == 0 then
        num = 1
    end
    local ret = math.random(num)
    if math.random(100) <= 50 then
        ret = -ret
    end
    return ret
end

--------------------------------------------------------------------------
local MAX_LIFETIME = 0.8

local function InitEnvelope()
    EnvelopeManager:AddColourEnvelope(
        COLOUR_ENVELOPE_NAME_RAINBOW_NPC_FX,
            {
                { 0,    IntColour(255, 255, 255, 255) },
                { 1,    IntColour(255, 255, 255, 0) },
            }
        )
    
    local scale_num_x = 0.4
    local scale_num_y = 0.5
    EnvelopeManager:AddVector2Envelope(
        SCALE_ENVELOPE_NAME_RAINBOW_POINT_NPC_FX,
        {
            { 0,  { scale_num_x, scale_num_y } },
            { 1,  { scale_num_x, scale_num_y } },
        }
    )
    InitEnvelope = nil
    IntColour = nil
end

local emit_fn = function(effect, sphere_emitter)
    local vx, vy, vz = 0,0,0
    -- local lifetime = MAX_LIFETIME * (.9 + UnitRand() * .1)
    local lifetime = MAX_LIFETIME
    local px, py, pz = sphere_emitter()

    local dx = RandomVectorDelta(100)/1000
    local dy = 0
    local dz = RandomVectorDelta(100)/1000

    local height = 1.25

    px = px + dx
    py = py + dy + height 
    pz = pz + dz

    effect:AddRotatingParticleUV(
        0,                --- 从0开始的
        lifetime,           -- lifetime
        px, py, pz,         -- position
        vx, vy, vz,         -- velocity
        0,--* 2 * PI, -- angle
        0,     -- angle velocity
        0, 0                -- uv offset
    )
    
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddNetwork()

    inst:AddTag("FX")

    inst.entity:SetPristine()

    inst.persists = false

    --Dedicated server does not need to spawn local particle fx
    if TheNet:IsDedicated() then
        return inst
    elseif InitEnvelope ~= nil then
        InitEnvelope()
    end

    local effect = inst.entity:AddVFXEffect()
    effect:InitEmitters(1)
    -----------------------------------------------------
    
    
    local num = 0
    effect:SetRenderResources(num, TEXTURE, SHADER)
    effect:SetMaxNumParticles(num, 32)
    effect:SetMaxLifetime(num,MAX_LIFETIME)
    effect:SetColourEnvelope(num, COLOUR_ENVELOPE_NAME_RAINBOW_NPC_FX)
    effect:SetScaleEnvelope(num, SCALE_ENVELOPE_NAME_RAINBOW_POINT_NPC_FX)
    effect:SetBlendMode(num, BLENDMODE.Additive) --AlphaBlended Premultiplied Additive
    effect:EnableBloomPass(num, true)
    effect:SetUVFrameSize(num, 1, 1)
    effect:SetSortOrder(num, -1)
    effect:SetSortOffset(num, 10)
    effect:SetRotationStatus(num, true)

    -----------------------------------------------------
    local tick_time = TheSim:GetTickTime()
    local smoke_desired_pps = 10
    local smoke_particles_per_tick = smoke_desired_pps * tick_time
    local smoke_num_particles_to_emit = -1 --start delay
    local sphere_emitter = CreateSphereEmitter(.05)
    EmitterManager:AddEmitter(inst, nil, function()
        while smoke_num_particles_to_emit > 1 do
            emit_fn(effect, sphere_emitter)
            smoke_num_particles_to_emit = smoke_num_particles_to_emit - 1
        end
        smoke_num_particles_to_emit = smoke_num_particles_to_emit + smoke_particles_per_tick
    end)



    return inst
end


local function fn_task()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddNetwork()

    if not TheNet:IsDedicated() then --- client only
        inst:DoTaskInTime(0,function()
            inst:SpawnChild("npc_fx_rainbow_base")
        end)
        inst:DoTaskInTime(0.3,function()
            inst:SpawnChild("npc_fx_rainbow_base")
        end)
    end

    inst:DoTaskInTime(480,inst.Remove)
    return inst
end

return Prefab("npc_fx_rainbow_base", fn, assets),Prefab("npc_fx_rainbow", fn_task)
